package com.sdkx.wear_os.retrofit

import androidx.lifecycle.viewModelScope
import com.sdkx.wear_os.base.BaseViewModel
import com.sdkx.wear_os.retrofit.response.BaseResponse
import com.sdkx.wear_os.utils.ExceptionHandle
import com.sdkx.wear_os.utils.ExceptionHandle.getExceptionInfo
import kotlinx.coroutines.*
import retrofit2.Response

/**
 * 协程请求数据 获取Data数据
 * @param block 请求体方法，必须要用suspend关键字修饰
 * @param success 成功回调
 * @param error 失败回调 可不传
 * @param logout 登录失效 可不传
 * @param isShowLoading 是否显示加载框
 * @param url 请求地址
 */
fun <T> BaseViewModel.launch(
    block: suspend () -> BaseResponse<T>,
    success: (T) -> Unit,
    error: (String) -> Unit,
    logout: (Boolean) -> Unit,
    isShowLoading: Boolean = false,
    url: String = ""
) {
    viewModelScope.launch {
        if (isShowLoading) loadingChange.showDialog.emit(true)
        kotlin.runCatching {
            //请求代码块调度在Io线程中
            withContext(Dispatchers.IO) { block() }
        }.onSuccess { its ->
            MainScope().launch {
                loadingChange.showDialog.emit(false)
            }
            try {
                //防止请求结果出错
                executeResponse(its, logout, { error(it) }) { success(it) }
            } catch (e: Exception) {
                error(ExceptionHandle.handleException(e))
                //上传错误
                if (url != "uploadError") {
                    val parameter = Parameter()
                    parameter.errorTitle = e.toString()
                    parameter.errorUrl = url
                    val errorStr = getExceptionInfo(e)
                    parameter.errorContent = errorStr
                    uploadError(parameter)
                }
            }
        }.onFailure {
            MainScope().launch {
                loadingChange.showDialog.emit(false)
                //上传错误
                if (url != "uploadError") {
                    val parameter = Parameter()
                    parameter.errorTitle = it.toString()
                    parameter.errorUrl = url
                    val errorStr = getExceptionInfo(it)
                    parameter.errorContent = errorStr
                    uploadError(parameter)
                }
            }
            error(ExceptionHandle.handleException(it))
        }
    }
}

/**
 * 协程请求数据 获取整条数据
 * @param block 请求体方法，必须要用suspend关键字修饰
 * @param success 成功回调
 * @param error 失败回调 可不传
 * @param logout 登录失效 可不传
 * @param isShowLoading 是否显示加载框
 * @param url 请求地址
 */
fun <T> BaseViewModel.launchData(
    block: suspend () -> BaseResponse<T>,
    success: (BaseResponse<T>) -> Unit,
    error: (String) -> Unit,
    logout: (Boolean) -> Unit,
    isShowLoading: Boolean = false,
    url: String = ""
) {
    viewModelScope.launch {
        if (isShowLoading) loadingChange.showDialog.emit(true)
        kotlin.runCatching {
            //请求代码块调度在Io线程中
            withContext(Dispatchers.IO) { block() }
        }.onSuccess { its ->
            MainScope().launch {
                loadingChange.showDialog.emit(false)
            }
            try {
                executeResponseData(its, logout, { error(it) }) {
                    success(it)
                }
            } catch (e: Exception) {
                if (e.message != "")
                    error(ExceptionHandle.handleException(e))
                //上传错误
                if (url != "uploadError") {
                    val parameter = Parameter()
                    parameter.errorTitle = e.toString()
                    parameter.errorUrl = url
                    val errorStr = getExceptionInfo(e)
                    parameter.errorContent = errorStr
                    uploadError(parameter)
                }
            }
        }.onFailure {
            MainScope().launch {
                loadingChange.showDialog.emit(false)
                //上传错误
                if (url != "uploadError") {
                    val parameter = Parameter()
                    parameter.errorTitle = it.toString()
                    parameter.errorUrl = url
                    val errorStr = getExceptionInfo(it)
                    parameter.errorContent = errorStr
                    uploadError(parameter)
                }
            }
            error(ExceptionHandle.handleException(it))
        }
    }
}

/**
 * 协程请求数据 获取全部数据
 */
fun <T> BaseViewModel.launchResponse(
    block: suspend () -> Response<T>,
    success: (Response<T>) -> Unit,
    error: (String) -> Unit,
    isShowLoading: Boolean = false
) {
    viewModelScope.launch {
        if (isShowLoading) loadingChange.showDialog.emit(true)
        kotlin.runCatching { withContext(Dispatchers.IO) { block() } }.onSuccess { its ->
            loadingChange.showDialog.emit(false)
            success(its)
        }.onFailure {
            loadingChange.showDialog.emit(false)
            error(ExceptionHandle.handleException(it))
        }
    }
}

suspend fun <T> BaseViewModel.executeResponse(
    response: BaseResponse<T>,
    logout: (Boolean) -> Unit,
    error: (String) -> Unit,
    success: suspend CoroutineScope.(T) -> Unit
) {
    coroutineScope {
        when (response.code) {
            "200", "20000" -> {
                response.data?.let { success(it) }
            }
            "login_out" -> {
                logout(true)
            }
            "500", "50000" -> {
                error(response.msg)
            }
            else -> {
                throw Exception(response.msg)
            }
        }
    }
}

suspend fun <T> BaseViewModel.executeResponseData(
    response: BaseResponse<T>,
    logout: (Boolean) -> Unit,
    error: suspend CoroutineScope.(String) -> Unit,
    success: suspend CoroutineScope.(BaseResponse<T>) -> Unit
) {

    coroutineScope {
        when (response.code) {
            "200", "20000" -> {
                success(response)
            }
            "login_out" -> {
                logout(true)
            }
            "500", "50000" -> {
                error(response.msg)
            }
            else -> {
                throw Exception(response.msg)
            }
        }
    }
}
